﻿#include "VulkanPointLights.h"
#include "Render/Widget/VulkanViewportWidget.h"
#include "Render/Scene/VulkanScene.h"
#include "Render/Scene/DefferRenderAttachments.h"
#include "Render/Widget/VulkanViewportWidget.h"

void CVulkanPointLights::PreProcess(const TVector<SPreRenderPointLight> &InPointLights, CVulkanViewportWidget* InViewport)
{
    //剔除与视椎体不相交的点光源
    PointLights.Clear();

    for (const SPreRenderPointLight &PointLight : InPointLights)
    {
        //检查参数是否合法
        if(PointLight.Radius<=0.0f)
        {
            continue;
        }

        if(PointLight.Intensity<=0.0f)
        {
            continue;
        }

        if(PointLight.Color.R<=0 && PointLight.Color.G<=0 && PointLight.Color.B<=0)
        {
            continue;
        }

        //检查点光源在视锥体内
        if (!InViewport->FastIsSphereIntersectFrustum(PointLight.Position, PointLight.Radius))
        {
            continue;
        }
        
        PointLights.Add(PointLight);
    }

    //统计描述符数量
    //点光源阴影图描述符
    SVulkanDescriptorPoolSize PoolSize;
    PoolSize.SetNum= 6*PointLights.Num();
    PoolSize+=CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapDescriptorSetLayout.DescriptorNums*6 * PointLights.Num();
    CVulkanContext::Get()->GetAutoResetDescriptorPool()->GenerallPool.PoolSize+=PoolSize;

    //点光源延迟渲染描述符
    SVulkanDescriptorPoolSize PoolSize2;
    PoolSize2.SetNum=PointLights.Num();
    PoolSize2+=CVulkanContext::Get()->GetSceneGlobal()->PointLightDefferShadingDescriptorSetLayout.DescriptorNums*PointLights.Num();
    CVulkanContext::Get()->GetAutoResetDescriptorPool()->GenerallPool.PoolSize+=PoolSize2;

    //生成阴影贴图
    RenderLights.Resize(PointLights.Num());
    for(int i=0;i<PointLights.Num();++i)
    {
        RenderLights[i].SetPointLight(PointLights[i]);
        RenderLights[i].LightIndex=i;
    }
}

int64_t CVulkanPointLights::GetPointLightNum() const
{
    return PointLights.Num();
}

bool CVulkanPointLights::IsInLightRange(int64_t InLightIndex, const SVec3 &InSpherePosition, float InSphereRadius)
{
    assert(InLightIndex<PointLights.Num());

    return ((PointLights[InLightIndex].Position- InSpherePosition).GetLength())<(PointLights[InLightIndex].Radius+InSphereRadius);
}

void CVulkanPointLights::RecordShadowMapCommand(vk::CommandBuffer InCmdBuffers, CVulkanScene *InScene)
{
    //记录命令
    for(int i=0;i<PointLights.Num();++i)
    {
        RenderLights[i].RecordShadowMapCommand(InCmdBuffers,InScene);
    }
}
void CVulkanPointLights::RecordDefferShadingCommand(vk::CommandBuffer InCmdBuffers, CVulkanScene *InScene, const SSceneParameters &InParameters, CDefferRenderAttachments *Attachments)
{
    InCmdBuffers.bindPipeline(vk::PipelineBindPoint::eGraphics, CVulkanContext::Get()->GetSceneGlobal()->PointLightDefferShadingPipeline);
    //记录延迟着色命令
    for(int i=0;i<PointLights.Num();++i)
    {
        RenderLights[i].RecordDefferShadingCommand(
            InCmdBuffers
            ,InScene
            ,InParameters
            ,Attachments
            );
    }
}

CVulkanPointLight::CVulkanPointLight()
{
    //生成缓冲区
    for(int32_t i=0;i<6;++i)
    {
        ShadowMapBuffer[i]=std::make_shared<TVulkanUniformBuffer<CSceneGlobal::SPointLightShadowMapBuffer>>();
    }

    //创建渲染目标
    Resize(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapExtent.width
        ,CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapExtent.height);
    
}

CVulkanPointLight::~CVulkanPointLight()
{
    //清除资源
    if(FrameBuffer)
    {
        CVulkanContext::Get()->GetDevice().destroyImageView(ImageView);
        ImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(Image);
        Image=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(MemoryBlock);

        CVulkanContext::Get()->GetDevice().destroyImageView(DepthImageView);
        DepthImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(DepthImage);
        DepthImage=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(DepthMemoryBlock);

        CVulkanContext::Get()->GetDevice().destroyFramebuffer(FrameBuffer);
        FrameBuffer=nullptr;

        CVulkanContext::Get()->GetDevice().destroyImageView(CubeImageView);
        CubeImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(CubeImage);
        CubeImage=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(CubeMemoryBlock);
    }
}

void CVulkanPointLight::Resize(uint32_t InWidth, uint32_t InHeight)
{
    if(Width==InWidth && Height==InHeight)
    {
        return;
    }

    //清除原有资源
    if(FrameBuffer)
    {
        CVulkanContext::Get()->GetDevice().destroyImageView(ImageView);
        ImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(Image);
        Image=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(MemoryBlock);

        CVulkanContext::Get()->GetDevice().destroyImageView(DepthImageView);
        DepthImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(DepthImage);
        DepthImage=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(DepthMemoryBlock);

        CVulkanContext::Get()->GetDevice().destroyFramebuffer(FrameBuffer);
        FrameBuffer=nullptr;

        CVulkanContext::Get()->GetDevice().destroyImageView(CubeImageView);
        CubeImageView=nullptr;
        CVulkanContext::Get()->GetDevice().destroyImage(CubeImage);
        CubeImage=nullptr;
        CVulkanContext::Get()->GetMemoryPools()->DeallocateBlock(CubeMemoryBlock);
    }

    Width=InWidth;
    Height=InHeight;

    if(Width==0 || Height==0)
    {
        return;
    }

    //创建资源对象
    vk::ImageCreateInfo ImageCreateInfo= vk::ImageCreateInfo()
        .setImageType(vk::ImageType::e2D)
        .setFormat(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapImageFormat)
        .setExtent(vk::Extent3D(Width,Height,1))
        .setMipLevels(1)
        .setArrayLayers(1)
        .setSamples(vk::SampleCountFlagBits::e1)
        .setTiling(vk::ImageTiling::eOptimal)
        .setUsage(vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferSrc)
        .setSharingMode(vk::SharingMode::eExclusive)
        .setQueueFamilyIndexCount(0)
        .setPQueueFamilyIndices(nullptr)
        .setInitialLayout(vk::ImageLayout::eUndefined);
    
    Image=CVulkanContext::Get()->GetDevice().createImage(ImageCreateInfo);
    vk::MemoryRequirements MemoryRequirements = CVulkanContext::Get()
        ->GetDevice().getImageMemoryRequirements(Image);
    auto MemoryTypeIndex= CVulkanContext::Get()->GetMemoryTypeIndex(MemoryRequirements, vk::MemoryPropertyFlagBits::eDeviceLocal);

    MemoryBlock=CVulkanContext::Get()->GetMemoryPools()->AllocateBlock(
        EVulkanMemoryUsage::Texture
        ,MemoryTypeIndex
        ,MemoryRequirements.size
    );

    CVulkanContext::Get()->GetDevice().bindImageMemory(Image, MemoryBlock.Memory, MemoryBlock.Offset);

    vk::ImageViewCreateInfo ImageViewCreateInfo= vk::ImageViewCreateInfo()
        .setImage(Image)
        .setViewType(vk::ImageViewType::e2D)
        .setFormat(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapImageFormat)
        .setComponents(vk::ComponentMapping())
        .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor,0,1,0,1));

    ImageView=CVulkanContext::Get()->GetDevice().createImageView(ImageViewCreateInfo);

    //深度图
    vk::ImageCreateInfo DepthImageCreateInfo= vk::ImageCreateInfo()
        .setImageType(vk::ImageType::e2D)
        .setFormat(vk::Format::eD16Unorm)
        .setExtent(vk::Extent3D(Width,Height,1))
        .setMipLevels(1)
        .setArrayLayers(1)
        .setSamples(vk::SampleCountFlagBits::e1)
        .setTiling(vk::ImageTiling::eOptimal)
        .setUsage(vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eTransferDst)
        .setSharingMode(vk::SharingMode::eExclusive)
        .setQueueFamilyIndexCount(0)
        .setPQueueFamilyIndices(nullptr)
        .setInitialLayout(vk::ImageLayout::eUndefined);

    DepthImage=CVulkanContext::Get()->GetDevice().createImage(DepthImageCreateInfo);

    MemoryRequirements = CVulkanContext::Get()->GetDevice().getImageMemoryRequirements(DepthImage);
    MemoryTypeIndex= CVulkanContext::Get()->GetMemoryTypeIndex(MemoryRequirements, vk::MemoryPropertyFlagBits::eDeviceLocal);

    DepthMemoryBlock=CVulkanContext::Get()->GetMemoryPools()->AllocateBlock(
        EVulkanMemoryUsage::Texture
        ,MemoryTypeIndex
        ,MemoryRequirements.size
    );

    CVulkanContext::Get()->GetDevice().bindImageMemory(DepthImage, DepthMemoryBlock.Memory, DepthMemoryBlock.Offset);

    vk::ImageViewCreateInfo DepthImageViewCreateInfo= vk::ImageViewCreateInfo()
        .setImage(DepthImage)
        .setViewType(vk::ImageViewType::e2D)
        .setFormat(vk::Format::eD16Unorm)
        .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth,0,1,0,1));

    DepthImageView=CVulkanContext::Get()->GetDevice().createImageView(DepthImageViewCreateInfo);


    //创建帧缓冲
    TVector<vk::ImageView> Attachments={ImageView,DepthImageView};

    vk::FramebufferCreateInfo FrameBufferCreateInfo= vk::FramebufferCreateInfo()
        .setRenderPass(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapRenderPass)
        .setAttachments(Attachments)
        .setWidth(Width)
        .setHeight(Height)
        .setLayers(1);

    FrameBuffer=CVulkanContext::Get()->GetDevice().createFramebuffer(FrameBufferCreateInfo);


    //立方体贴图
    vk::ImageCreateInfo CubeImageCreateInfo= vk::ImageCreateInfo()
        .setFlags(vk::ImageCreateFlagBits::eCubeCompatible)
        .setImageType(vk::ImageType::e2D)
        .setFormat(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapImageFormat)
        .setExtent(vk::Extent3D(Width,Height,1))
        .setMipLevels(1)
        .setArrayLayers(6)
        .setSamples(vk::SampleCountFlagBits::e1)
        .setTiling(vk::ImageTiling::eOptimal)
        .setUsage(vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst )
        .setSharingMode(vk::SharingMode::eExclusive)
        .setQueueFamilyIndexCount(0)
        .setPQueueFamilyIndices(nullptr)
        .setInitialLayout(vk::ImageLayout::eUndefined);

    CubeImage=CVulkanContext::Get()->GetDevice().createImage(CubeImageCreateInfo);

    MemoryRequirements = CVulkanContext::Get()->GetDevice().getImageMemoryRequirements(CubeImage);
    MemoryTypeIndex= CVulkanContext::Get()->GetMemoryTypeIndex(MemoryRequirements, vk::MemoryPropertyFlagBits::eDeviceLocal);

    CubeMemoryBlock=CVulkanContext::Get()->GetMemoryPools()->AllocateBlock(
        EVulkanMemoryUsage::Texture
        ,MemoryTypeIndex
        ,MemoryRequirements.size
    );
    
    CVulkanContext::Get()->GetDevice().bindImageMemory(CubeImage, CubeMemoryBlock.Memory, CubeMemoryBlock.Offset);

    vk::ImageViewCreateInfo CubeImageViewCreateInfo= vk::ImageViewCreateInfo()
        .setImage(CubeImage)
        .setViewType(vk::ImageViewType::eCube)
        .setFormat(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapImageFormat)
        .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor,0,1,0,6));

    CubeImageView=CVulkanContext::Get()->GetDevice().createImageView(CubeImageViewCreateInfo);



}

void CVulkanPointLight::SetPointLight(const SPreRenderPointLight &InPointLight)
{
    RenderData=InPointLight;

    ProjectionMatrix=SMatrix4x4::
        Perspective(CMathBase::DegreeToRadian(90.0f) 
        , 1.0f
        , 0.1f
        , InPointLight.Radius);

    ViewMatrix[int(ECubicDirection::Forward)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(0,1,0),SVec3(0,0,1));
    ViewMatrix[int(ECubicDirection::Backward)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(0,-1,0),SVec3(0,0,-1));
    ViewMatrix[int(ECubicDirection::Right)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(1,0,0),SVec3(0,-1,0));
    ViewMatrix[int(ECubicDirection::Left)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(-1,0,0),SVec3(0,-1,0));
    ViewMatrix[int(ECubicDirection::Top)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(0,0,1),SVec3(0,-1,0));
    ViewMatrix[int(ECubicDirection::Bottom)]=
        SMatrix4x4::LookAt(InPointLight.Position, SVec3(0,0,-1),SVec3(0,-1,0));



    //写入缓冲区
    CSceneGlobal::SPointLightShadowMapBuffer ShadowMapBufferContent;
    InPointLight.Position.ToFloatArray(ShadowMapBufferContent.LightPosition);
    for(int i=0;i<6;i++)
    {
        (ProjectionMatrix*ViewMatrix[i]).ToFloatArray(ShadowMapBufferContent.ProjectionViewMatrix);
        ShadowMapBuffer[i]->WriteData(ShadowMapBufferContent);
    }


}

void CVulkanPointLight::UpdateDescriptor()
{
    assert(ShadowMapBuffer[0]!=nullptr);

    //生成描述符
    SVulkanDescriptorLayout DescriptorLayout=CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapDescriptorSetLayout;

    TVector<vk::DescriptorSetLayout> DescriptorLayouts=
    {
        DescriptorLayout.Layout,
        DescriptorLayout.Layout,
        DescriptorLayout.Layout,
        DescriptorLayout.Layout,
        DescriptorLayout.Layout,
        DescriptorLayout.Layout,
    };

    vk::DescriptorSetAllocateInfo DescriptorSetAllocateInfo = vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(CVulkanContext::Get()->GetAutoResetDescriptorPool()->GenerallPool.Pool)
        .setDescriptorSetCount(6)
        .setSetLayouts(DescriptorLayouts);

    auto Sets=CVulkanContext::Get()->GetDevice().allocateDescriptorSets(DescriptorSetAllocateInfo);

    for(int i=0;i<6;++i)
    {
        ShadowMapDescriptorSet[i]=Sets[i];

        vk::DescriptorBufferInfo BufferInfo= vk::DescriptorBufferInfo()
            .setBuffer(ShadowMapBuffer[i]->GetBuffer())
            .setOffset(0)
            .setRange(ShadowMapBuffer[i]->GetSize());

        TVector<vk::WriteDescriptorSet> WriteDescriptorSets=
        {
            vk::WriteDescriptorSet()
            .setDstSet(ShadowMapDescriptorSet[i])
            .setDstBinding(0)
            .setDstArrayElement(0)
            .setDescriptorCount(1)
            .setDescriptorType(vk::DescriptorType::eUniformBuffer)
            .setPBufferInfo(&BufferInfo)
        };

        CVulkanContext::Get()->GetDevice().updateDescriptorSets(WriteDescriptorSets, nullptr);
    }

}

void CVulkanPointLight::RecordShadowMapCommand(vk::CommandBuffer InCmdBuffers,CVulkanScene* InScene)
{
    //生成描述符
    UpdateDescriptor();

    //改变立方体贴图的布局以便复制
    auto CubeImageMemoryBarrier = vk::ImageMemoryBarrier()
            .setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
            .setDstAccessMask(vk::AccessFlagBits::eTransferRead)
            .setOldLayout(vk::ImageLayout::eUndefined)
            .setNewLayout(vk::ImageLayout::eTransferDstOptimal)
            .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setImage(CubeImage)
            .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor,0,1,0,6));

    InCmdBuffers.pipelineBarrier(
        vk::PipelineStageFlagBits::eAllCommands
        , vk::PipelineStageFlagBits::eAllCommands
        , vk::DependencyFlags()
        , nullptr
        , nullptr
        , CubeImageMemoryBarrier
    );


    TVector<vk::ClearValue> ClearValues =
    {
        vk::ClearColorValue(std::array<float,4>{-1.f /*无符号的最大值*/,0.0f,0.0f,0.0f}),
        vk::ClearDepthStencilValue(1.0f, 0)
    };
    vk::RenderPassBeginInfo RenderPassBeginInfo = vk::RenderPassBeginInfo()
        .setRenderPass(CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapRenderPass)
        .setFramebuffer(FrameBuffer)
        .setRenderArea(vk::Rect2D(vk::Offset2D(0, 0), CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapExtent))
        .setClearValues(ClearValues);

    for(int FaceIndex=0;FaceIndex<6;FaceIndex++)
    {
        InCmdBuffers.beginRenderPass(RenderPassBeginInfo, vk::SubpassContents::eInline);

        InCmdBuffers.bindPipeline(
                vk::PipelineBindPoint::eGraphics
                ,CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapPipeline);

        SMatrix4x4 ProjectViewMatrix= ProjectionMatrix * ViewMatrix[FaceIndex];

        for (const auto& MeshInstanceIndex : InScene->GetMeshInstancePainter()->PointLightShadowMapMeshMap[LightIndex])
        {
            auto& MeshInstance =InScene->GetMeshInstancePainter()->MeshInstances[MeshInstanceIndex];

            //绑定描述符集
            InCmdBuffers.bindDescriptorSets(
                vk::PipelineBindPoint::eGraphics
                ,CVulkanContext::Get()->GetSceneGlobal()->PointLightShadowMapPipelineLayout
                ,0
                ,{ShadowMapDescriptorSet[FaceIndex],MeshInstance.GetModelUniformDescriptorSet()} 
                ,{});

            //draw mesh
            MeshInstance.RecordDrawVertexCommands(InCmdBuffers);
        }
      
        InCmdBuffers.endRenderPass();


        //复制到立方体贴图
        vk::ImageMemoryBarrier ImageMemoryBarrier = vk::ImageMemoryBarrier()
            .setSrcAccessMask(vk::AccessFlagBits::eShaderWrite)
            .setDstAccessMask(vk::AccessFlagBits::eTransferRead)
            .setOldLayout(vk::ImageLayout::eColorAttachmentOptimal)
            .setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
            .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setImage(Image)
            .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));

        InCmdBuffers.pipelineBarrier(
            vk::PipelineStageFlagBits::eFragmentShader
            , vk::PipelineStageFlagBits::eTransfer
            , vk::DependencyFlags()
            , nullptr
            , nullptr
            , ImageMemoryBarrier
        );


        vk::ImageSubresourceLayers SrcSubresourceLayers = vk::ImageSubresourceLayers()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setMipLevel(0)
            .setBaseArrayLayer(0)
            .setLayerCount(1);

        vk::ImageSubresourceLayers DstSubresourceLayers = vk::ImageSubresourceLayers()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setMipLevel(0)
            .setBaseArrayLayer(FaceIndex)
            .setLayerCount(1);

        vk::ImageCopy ImageCopy = vk::ImageCopy()
            .setSrcSubresource(SrcSubresourceLayers)
            .setSrcOffset(vk::Offset3D(0, 0, 0))
            .setDstSubresource(DstSubresourceLayers)
            .setDstOffset(vk::Offset3D(0, 0, 0))
            .setExtent(vk::Extent3D(Width, Height, 1));

        InCmdBuffers.copyImage(
            Image
            , vk::ImageLayout::eTransferSrcOptimal
            , CubeImage
            , vk::ImageLayout::eTransferDstOptimal
            , ImageCopy
        );

        //恢复Image的布局
        ImageMemoryBarrier = vk::ImageMemoryBarrier()
            .setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
            .setDstAccessMask(vk::AccessFlagBits::eShaderWrite)
            .setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
            .setNewLayout(vk::ImageLayout::eColorAttachmentOptimal)
            .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
            .setImage(Image)
            .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));

        InCmdBuffers.pipelineBarrier(
            vk::PipelineStageFlagBits::eTransfer
            , vk::PipelineStageFlagBits::eFragmentShader
            , vk::DependencyFlags()
            , nullptr
            , nullptr
            , ImageMemoryBarrier
        );
    }

    //改变立方体贴图的布局以便采样
    CubeImageMemoryBarrier = vk::ImageMemoryBarrier()
        .setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
        .setDstAccessMask(vk::AccessFlagBits::eShaderRead)
        .setOldLayout(vk::ImageLayout::eTransferDstOptimal)
        .setNewLayout(vk::ImageLayout::eShaderReadOnlyOptimal)
        .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
        .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
        .setImage(CubeImage)
        .setSubresourceRange(vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor,0,1,0,6));

    InCmdBuffers.pipelineBarrier(
        vk::PipelineStageFlagBits::eTransfer
        , vk::PipelineStageFlagBits::eFragmentShader
        , vk::DependencyFlags()
        , nullptr
        , nullptr
        , CubeImageMemoryBarrier
    );

}

void CVulkanPointLight::RecordDefferShadingCommand(
    vk::CommandBuffer InCmdBuffers
    ,CVulkanScene *InScene
    ,const SSceneParameters& InParameters 
    ,CDefferRenderAttachments* Attachments
    )
{
    //创建延迟着色描述符
    vk::DescriptorSetAllocateInfo DescriptorSetAllocateInfo = vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(CVulkanContext::Get()->GetAutoResetDescriptorPool()->GenerallPool.Pool)
        .setDescriptorSetCount(1)
        .setPSetLayouts(&CVulkanContext::Get()->GetSceneGlobal()->PointLightDefferShadingDescriptorSetLayout.Layout);

    vk::DescriptorSet DescriptorSet=
        CVulkanContext::Get()->GetDevice().allocateDescriptorSets(DescriptorSetAllocateInfo)[0];

    //写入描述符
    vk::DescriptorImageInfo ImageInfo= vk::DescriptorImageInfo()
        .setSampler(CVulkanContext::Get()->GetSceneGlobal()->ShadowMapSampler)
        .setImageView(CubeImageView)
        .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal);

    vk::WriteDescriptorSet WriteDescriptorSet= vk::WriteDescriptorSet()
        .setDstSet(DescriptorSet)
        .setDstBinding(0)
        .setDstArrayElement(0)
        .setDescriptorCount(1)
        .setDescriptorType(vk::DescriptorType::eCombinedImageSampler)
        .setPImageInfo(&ImageInfo);

    CVulkanContext::Get()->GetDevice().updateDescriptorSets(WriteDescriptorSet, nullptr);


    //绘制
    InCmdBuffers.bindDescriptorSets(vk::PipelineBindPoint::eGraphics
        , CVulkanContext::Get()->GetSceneGlobal()->PointLightDefferShadingPipelineLayout
        , 0
        , { Attachments->DescriptorSet, DescriptorSet}
        , {}
    );

    //push constants
    SPointLightDefferShadingFragmentPushConstant PushConstant;
    SColor ColorWithIntensity=RenderData.Color * RenderData.Intensity;
    ColorWithIntensity.ToFloatArray(PushConstant.ColorWithIntensity);
    RenderData.Position.ToFloatArray(PushConstant.Position);
    PushConstant.Radius = RenderData.Radius;
    PushConstant.ViewPos[0] = InParameters.CameraPosition[0];
    PushConstant.ViewPos[1] = InParameters.CameraPosition[1];
    PushConstant.ViewPos[2] = InParameters.CameraPosition[2];
    PushConstant.ShadowBias = RenderData.ShadowBias;

    InCmdBuffers.pushConstants(
            CVulkanContext::Get()->GetSceneGlobal()->PointLightDefferShadingPipelineLayout
            , vk::ShaderStageFlagBits::eFragment
            , 0
            , sizeof(SPointLightDefferShadingFragmentPushConstant)
            , &PushConstant
        );

    InCmdBuffers.draw(3, 1, 0, 0);

}
